

#ifndef _HOOK_H_
#define _HOOK_H_

#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <fcntl.h>

namespace zepco {

bool is_hook_enable();
void set_hook_enable(bool flag);

}

extern "C" {
    // track the original version
    typedef unsigned int (*sleep_t) (unsigned int seconds);
    extern sleep_t sleep_f;

    typedef int (*usleep_t) (useconds_t usec);
    extern usleep_t usleep_f;

    typedef int (*nanosleep_t) (const struct timespec *req, struct timespec *rem);
    extern nanosleep_t nanosleep_f;

    typedef int (*socket_t) (int domain, int type, int protocol);
    extern socket_t socket_f;

    typedef int (*connect_t) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    extern connect_t connect_f;

    typedef int (*accept_t) (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    extern accept_t accept_f;

    typedef ssize_t (*read_t) (int fd, void *buf, size_t count);
    extern read_t read_f;

    typedef ssize_t (*readv_t)(int fd, const struct iovec *iov, int iovcnt);
    extern readv_t readv_f;

    typedef ssize_t (*recv_t) (int sockfd, void *buf, size_t len, int flags);
    extern recv_t recv_f;

    typedef ssize_t (*recvfrom_t) (int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
    extern recvfrom_t recvfrom_f;

    typedef ssize_t (*recvmsg_t) (int sockfd, struct msghdr *msg, int flags);
    extern recvmsg_t recvmsg_f;

    typedef ssize_t (*write_t) (int fd, const void *buf, size_t count);
    extern write_t write_f;

    typedef ssize_t (*writev_t) (int fd, const struct iovec *iov, int iovcnt);
    extern writev_t writev_f;

    typedef ssize_t (*send_t) (int sockfd, const void *buf, size_t len, int flags);
    extern send_t send_f;

    typedef ssize_t (*sendto_t) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
    extern sendto_t sendto_f;

    typedef ssize_t (*sendmsg_t) (int sockfd, const struct msghdr *msg, int flags);
    extern sendmsg_t sendmsg_f;

    typedef int (*close_t) (int fd);
    extern close_t close_f;

    typedef int (*fcntl_t) (int fd, int cmd, ... /* arg */ );
    extern fcntl_t fcntl_f;

    typedef int (*ioctl_t) (int fd, unsigned long request, ...);
    extern ioctl_t ioctl_f;

    typedef int (*getsockopt_t) (int sockfd, int level, int optname, void *optval, socklen_t *optlen);
    extern getsockopt_t getsockopt_f;

    typedef int (*setsockopt_t) (int sockfd, int level, int optname, const void *optval, socklen_t optlen);
    extern setsockopt_t setsockopt_f;

    // function prototype -> 对应.h中已经存在 可以省略
    // sleep function
    unsigned int sleep(unsigned int seconds);
    int usleep(useconds_t usce);
    int nanosleep(const struct timespec *req, struct timespec *rem);

    //////////////////////////  io  ///////////////////////////
    // socket funciton
    int socket(int domain, int type, int protocol);
    int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    // read
    ssize_t read(int fd, void *buf, size_t count);
    ssize_t readv(int fd, const struct iovec *iov, int iovcnt);

    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
    ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    // write
    ssize_t write(int fd, const void *buf, size_t count);
    ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
    ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

    //////////////////////////////////////////////////////////
    // fd
    int close(int fd);

    // socket control
    int fcntl(int fd, int cmd, ... /* arg */ );
    int ioctl(int fd, unsigned long request, ...);

    int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
    int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
}


#endif // _HOOK_H_